package com.ssy.lingxi.member.merchant.serviceimpl.web;

import com.ssy.lingxi.common.constant.member.MemberStatusEnum;
import com.ssy.lingxi.common.constant.member.MemberTypeEnum;
import com.ssy.lingxi.common.constant.member.RoleTypeEnum;
import com.ssy.lingxi.common.exception.BusinessException;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.member.merchant.api.constant.MemberRelationTypeEnum;
import com.ssy.lingxi.member.merchant.config.ServiceConfig;
import com.ssy.lingxi.member.merchant.entity.*;
import com.ssy.lingxi.member.merchant.model.constant.*;
import com.ssy.lingxi.member.merchant.model.vo.basic.request.MemberLogoVO;
import com.ssy.lingxi.member.merchant.model.vo.basic.request.MemberUpdateRegisterDetailVO;
import com.ssy.lingxi.member.merchant.model.vo.basic.response.MemberRegisterDetailVO;
import com.ssy.lingxi.member.merchant.model.vo.manage.request.MemberAndRoleIdVO;
import com.ssy.lingxi.member.merchant.model.vo.manage.response.UpperChannelVO;
import com.ssy.lingxi.member.merchant.repository.CountryCodeRepository;
import com.ssy.lingxi.member.merchant.repository.MemberRelationRepository;
import com.ssy.lingxi.member.merchant.repository.MemberRepository;
import com.ssy.lingxi.member.merchant.repository.MemberUserRepository;
import com.ssy.lingxi.member.merchant.service.base.IBaseMemberCacheService;
import com.ssy.lingxi.member.merchant.service.base.IBaseMemberRegisterDetailService;
import com.ssy.lingxi.member.merchant.service.web.IMemberMainPageService;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * “首页” - 相关接口
 * @author 万宁
 * @version 2.0.0
 * @date 2021-01-23
 */
@Service
public class MemberMainPageServiceImpl implements IMemberMainPageService {

    @Resource
    private IBaseMemberCacheService memberCacheService;

    @Resource
    private MemberRepository memberRepository;

    @Resource
    private MemberRelationRepository relationRepository;

    @Resource
    private MemberUserRepository memberUserRepository;

    @Resource
    private CountryCodeRepository countryCodeRepository;

    @Resource
    private IBaseMemberRegisterDetailService baseMemberRegisterDetailService;

    /**
     * 新增或修改会员Logo
     *
     * @param headers Http头部信息
     * @param logoVO  接口参数
     * @return 新增结果
     */
    @Transactional(rollbackFor = BusinessException.class)
    @Override
    public Wrapper<Void> addMemberUserLogo(HttpHeaders headers, MemberLogoVO logoVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);

        MemberUserDO memberUserDO = memberUserRepository.findById(loginUser.getUserId()).orElse(null);
        if(memberUserDO == null || memberUserDO.getMember() == null || !memberUserDO.getMember().getId().equals(loginUser.getMemberId())) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_USER_DOES_NOT_EXIST);
        }

        memberUserDO.setLogo(logoVO.getLogo());
        memberUserRepository.saveAndFlush(memberUserDO);

        if(memberUserDO.getTypeEnum().equals(MemberUserAuthTypeEnum.ADMIN.getCode())) {
            MemberDO memberDO = memberUserDO.getMember();
            memberDO.setLogo(logoVO.getLogo());
            memberRepository.saveAndFlush(memberDO);
        }

        return Wrapper.success();
    }

    /**
     * “首页” - 审核不通过时，查询会员注册资料信息
     *
     * @param headers Http头部信息
     * @return 查询结果
     */
    @Override
    public Wrapper<MemberRegisterDetailVO> getMemberRegisterDetail(HttpHeaders headers) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);

        MemberRelationDO relationDO = relationRepository.findFirstBySubMemberIdAndSubRoleIdAndRelType(loginUser.getMemberId(), loginUser.getMemberRoleId(), MemberRelationTypeEnum.PLATFORM.getCode());
        if (relationDO == null) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_RELATION_DOES_NOT_EXIST);
        }

        //审核不为“审核不通过”，即审核未完成，不能修改信息
        if (!relationDO.getInnerStatus().equals(PlatformInnerStatusEnum.VERIFY_NOT_PASSED.getCode())) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_VERIFYING);
        }

        MemberRegisterDetailVO detailVO = new MemberRegisterDetailVO();
        detailVO.setMemberId(relationDO.getSubMemberId());
        detailVO.setName(relationDO.getSubMember().getName());
        detailVO.setOuterStatus(relationDO.getOuterStatus());
        detailVO.setOuterStatusName(MemberOuterStatusEnum.getCodeMsg(relationDO.getOuterStatus()));
        detailVO.setStatus(relationDO.getStatus());
        detailVO.setStatusName(MemberStatusEnum.getCodeMessage(relationDO.getStatus()));
        detailVO.setMemberTypeEnum(relationDO.getSubRole().getMemberType().getTypeEnum());
        detailVO.setMemberTypeId(relationDO.getSubRole().getMemberType().getId());
        detailVO.setMemberTypeName(MemberTypeEnum.getCodeMessage(relationDO.getSubRole().getMemberType().getTypeEnum()));
        detailVO.setRoleId(relationDO.getSubRoleId());
        detailVO.setRoleName(relationDO.getSubRole().getRoleName());
        detailVO.setLevelId(relationDO.getLevelRight().getLevelConfig().getId());
        detailVO.setLevel(relationDO.getLevelRight().getLevel());
        detailVO.setLevelTag(relationDO.getLevelRight().getLevelTag());
        detailVO.setAccount(relationDO.getSubMember().getAccount());

        CountryCodeDO countryCode = countryCodeRepository.findFirstByCode(relationDO.getSubMember().getCountryCode());
        detailVO.setCountryCodeId(countryCode == null ? 0L : countryCode.getId());
        detailVO.setCountryCode(relationDO.getSubMember().getCountryCode());
        detailVO.setPhone(relationDO.getSubMember().getPhone());
        detailVO.setEmail(relationDO.getSubMember().getEmail());
        detailVO.setCreateTime(relationDO.getCreateTime().format(ServiceConfig.DEFAULT_DATETIME_FORMATTER));
        detailVO.setGroups(baseMemberRegisterDetailService.switchMemberRegisterDetail(relationDO.getSubMember()));

        return Wrapper.success(detailVO);
    }

    /**
     * “首页” - 审核不通过时，修改会员注册资料
     *
     * @param headers  Http头部信息
     * @param detailVO 接口参数
     * @return 操作结果
     */
    @Override
    public Wrapper<Void> updateMemberRegisterDetail(HttpHeaders headers, MemberUpdateRegisterDetailVO detailVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);

        //审核不通过时，修改信息，修改后自动提交审核
        MemberRelationDO relationDO = relationRepository.findFirstBySubMemberIdAndSubRoleIdAndRelType(loginUser.getMemberId(), loginUser.getMemberRoleId(), MemberRelationTypeEnum.PLATFORM.getCode());
        if (relationDO == null) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_RELATION_DOES_NOT_EXIST);
        }

        if(relationDO.getOuterStatus().equals(MemberOuterStatusEnum.TO_PLATFORM_VERIFY.getCode()) || relationDO.getOuterStatus().equals(MemberOuterStatusEnum.PLATFORM_VERIFYING.getCode())) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_HAS_ALREADY_COMMIT_TO_VALIDATE);
        }

        if(relationDO.getOuterStatus().equals(MemberOuterStatusEnum.PLATFORM_VERIFY_PASSED.getCode())) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_VALIDATE_HAS_COMPLETED);
        }

        return baseMemberRegisterDetailService.updatePlatformMemberRegisterDetail(relationDO, detailVO.getEmail(), detailVO.getDetail(), true, true);
    }

    /**
     * 查询当前会员角色、及上级渠道会员列表
     *
     * @param headers Http头部信息
     * @return 查询结果
     */
    @Override
    public Wrapper<List<UpperChannelVO>> findUpperChannels(HttpHeaders headers) {
        UserLoginCacheDTO loginUser = memberCacheService.checkUserFromCache(headers);
        MemberDO memberDO = memberRepository.findById(loginUser.getMemberId()).orElse(null);
        if(memberDO == null) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_DOES_NOT_EXIST);
        }

        List<RoleDO> channelRoles = memberDO.getRoles().stream().filter(roleDO -> roleDO.getMemberType().getTypeEnum().equals(MemberTypeEnum.CHANNEL.getCode()) || roleDO.getMemberType().getTypeEnum().equals(MemberTypeEnum.CHANNEL_PERSONAL.getCode())).collect(Collectors.toList());
        if(CollectionUtils.isEmpty(channelRoles)) {
            return Wrapper.success(new ArrayList<>());
        }

        List<Long> consumerRoleIds = channelRoles.stream().filter(roleDO -> roleDO.getRoleType().getTypeEnum().equals(RoleTypeEnum.SERVICE_CONSUMER.getCode())).map(RoleDO::getId).collect(Collectors.toList());
        if(CollectionUtils.isEmpty(consumerRoleIds)) {
            return Wrapper.success(channelRoles.stream().map(roleDO -> {
                UpperChannelVO channelVO = new UpperChannelVO();
                channelVO.setMemberId(loginUser.getMemberId());
                channelVO.setName(memberDO.getName());
                channelVO.setRoleId(roleDO.getId());
                channelVO.setRoleName(roleDO.getRoleName());
                channelVO.setRoleTypeEnum(roleDO.getRoleType().getTypeEnum());
                channelVO.setRoleTypeName(RoleTypeEnum.getName(roleDO.getRoleType().getTypeEnum()));
                channelVO.setUpperChannels(new ArrayList<>());
                return channelVO;
            }).collect(Collectors.toList()));
        }

        Specification<MemberRelationDO> specification = (Specification<MemberRelationDO>) (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            list.add(criteriaBuilder.equal(root.get("relType").as(Integer.class), MemberRelationTypeEnum.OTHER.getCode()));
            list.add(criteriaBuilder.equal(root.get("subMemberId").as(Long.class), loginUser.getMemberId()));
            list.add(criteriaBuilder.equal(root.get("verified").as(Integer.class), MemberValidateStatusEnum.VERIFY_PASSED.getCode()));
            list.add(criteriaBuilder.equal(root.get("status").as(Integer.class), MemberStatusEnum.NORMAL.getCode()));

            //In查询
            list.add(root.get("subRoleId").in(consumerRoleIds));
            Join<MemberRelationDO, RoleDO> roleJoin = root.join("role", JoinType.LEFT);
            list.add(criteriaBuilder.or(
                    criteriaBuilder.equal(roleJoin.get("memberType").get("typeEnum").as(Integer.class), MemberTypeEnum.CHANNEL.getCode()),
                    criteriaBuilder.equal(roleJoin.get("memberType").get("typeEnum").as(Integer.class), MemberTypeEnum.CHANNEL_PERSONAL.getCode())
            ));

            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        List<MemberRelationDO> upperChannels = relationRepository.findAll(specification);

        return Wrapper.success(channelRoles.stream().map(roleDO -> {
            UpperChannelVO channelVO = new UpperChannelVO();
            channelVO.setMemberId(loginUser.getMemberId());
            channelVO.setName(memberDO.getName());
            channelVO.setRoleId(roleDO.getId());
            channelVO.setRoleName(roleDO.getRoleName());
            channelVO.setRoleTypeEnum(roleDO.getRoleType().getTypeEnum());
            channelVO.setRoleTypeName(RoleTypeEnum.getName(roleDO.getRoleType().getTypeEnum()));

            if(roleDO.getRoleType().getTypeEnum().equals(RoleTypeEnum.SERVICE_PROVIDER.getCode())) {
                channelVO.setUpperChannels(new ArrayList<>());
            } else {
                List<MemberRelationDO> upperRelations = upperChannels.stream().filter(relationDO -> relationDO.getSubRoleId().equals(roleDO.getId())).collect(Collectors.toList());
                channelVO.setUpperChannels(upperRelations.stream().map(relationDO -> {
                    UpperChannelVO upperChannel = new UpperChannelVO();
                    upperChannel.setMemberId(relationDO.getMemberId());
                    upperChannel.setRoleId(relationDO.getRoleId());
                    upperChannel.setName(relationDO.getMember().getName());
                    upperChannel.setRoleName(relationDO.getRole().getRoleName());
                    upperChannel.setRoleTypeEnum(relationDO.getRole().getRoleType().getTypeEnum());
                    upperChannel.setRoleTypeName(RoleTypeEnum.getName(relationDO.getRole().getRoleType().getTypeEnum()));
                    upperChannel.setUpperChannels(new ArrayList<>());
                    return upperChannel;
                }).collect(Collectors.toList()));
            }

            return channelVO;
        }).collect(Collectors.toList()));
    }

    /**
     * 判断当前登录会员，是否指定会员的上级会员
     *
     * @param headers Http头部信息
     * @param idVO    接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<Boolean> isUpperMember(HttpHeaders headers, MemberAndRoleIdVO idVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        return Wrapper.success(relationRepository.existsByMemberIdAndRoleIdAndSubMemberIdAndSubRoleId(loginUser.getMemberId(), loginUser.getMemberRoleId(), idVO.getMemberId(), idVO.getRoleId()));
    }
}
